package com.followerback.resources;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import com.followerback.model.MatchedFollower;
import com.followerback.model.SearchPhrase;
import com.followerback.model.TwitterProfile;
import com.followerback.model.TwitterProfileChannel;
import com.google.appengine.api.channel.ChannelService;
import com.google.appengine.api.channel.ChannelServiceFactory;
import com.googlecode.objectify.Objectify;
import com.googlecode.objectify.ObjectifyService;

@Path("/searchPhrase")
public class SearchPhraseResource extends Resource {

	private static final Logger logger = Logger.getLogger(SearchPhraseResource.class.getName());
	
	@Path("/match")
	@POST
	@Produces(MediaType.TEXT_PLAIN)
	public Response addMatch(String text, @Context HttpServletRequest request) {
		
		
		/* Initial stuff */
		logger.info("Entering addMatch");
		long methodStartTime = System.currentTimeMillis();
		HttpSession httpSession = request.getSession(true);
		Long userID = (Long)httpSession.getAttribute("serverSideUserID");
		if(userID == null) {
			String errorReason = "User not logged in";
			logger.severe(errorReason);
			return Response.status(401).build();
		}
		if(text == null || text.isEmpty()) {
			String errorReason = "No text entered";
			logger.severe(errorReason);
			return Response.serverError().entity(errorReason).build();
		}
		Objectify objectify = ObjectifyService.begin();
		
		
		/* Add Search phrase */
		// find twitter profile
		TwitterProfile twitterProfile = objectify.find(TwitterProfile.class, userID);
		if(twitterProfile == null) {
			String errorReason = "Twitter profile not found";
			logger.severe(errorReason);
			return Response.status(401).build();
		}
		
		// check to make sure search phrase hasn't already been added
		// if not persist
		String lowerCaseText = text.toLowerCase();
		SearchPhrase searchPhrase = objectify.query(SearchPhrase.class)
				.filter("twitterProfileID", twitterProfile.getId()).filter("text", lowerCaseText).get();
		if(searchPhrase == null) {
			searchPhrase = new SearchPhrase(text.toLowerCase(), twitterProfile.getId(), false);
			objectify.put(searchPhrase);
		}
		
		
		/* End stuff */
		logger.info("Exiting addMatch in " +(System.currentTimeMillis() - methodStartTime)/1000d+ " secs");
		return Response.ok(text).build();
	}
	
	@Path("/search")
	@GET
	@Produces(MediaType.APPLICATION_JSON)
	public Response beginSearchForMatches(@Context HttpServletRequest request) {
		
		
		/* Initial stuff */
		logger.info("Entering beginSearchForMatches");
		long methodStartTime = System.currentTimeMillis();
		HttpSession httpSession = request.getSession(true);
		Long userID = (Long)httpSession.getAttribute("serverSideUserID");
		if(userID == null) {
			String errorReason = "User not logged in";
			logger.severe(errorReason);
			return Response.status(401).build();
		}
		Objectify objectify = ObjectifyService.begin();
		ChannelService channelService = ChannelServiceFactory.getChannelService();
		Map<String, Object> resultMap = new HashMap<String, Object>();
		
		
		/* Create Channel Token */
		// create profile token link delete any old ones
		List<TwitterProfileChannel> twitterProfileChannels = objectify
				.query(TwitterProfileChannel.class).filter("twitterProfileID", userID).list();
		
		// if there are any channel tokens with matched follower return them instead
		for(TwitterProfileChannel twitterProfileChannel : twitterProfileChannels) {
			List<MatchedFollower> matchedFollowers =  objectify.query(MatchedFollower.class)
					.filter("token", twitterProfileChannel.getChannelToken()).list();
			if(!matchedFollowers.isEmpty()) {
				resultMap.put("matchedFollowers", matchedFollowers);
				return Response.ok(gson.toJson(resultMap)).build();
			}
		}
		if(!twitterProfileChannels.isEmpty())
			objectify.delete(twitterProfileChannels);
		
		// create channel
		TwitterProfileChannel twitterProfileChannel = new TwitterProfileChannel(userID);
		objectify.put(twitterProfileChannel);
		String token = channelService.createChannel(""+ twitterProfileChannel.getId());
		twitterProfileChannel.setChannelToken(token);
		objectify.put(twitterProfileChannel);
		
		
		/* Begin Search */
		postToSearchUsersFollowers(userID, token);
		
		
		/* End stuff */
		resultMap.put("token", token);
		logger.info("Exiting beginSearchForMatches in " 
				+(System.currentTimeMillis() - methodStartTime)/1000d+ " secs");
		return Response.ok(token).build();
		
	}
	
	@Path("/check")
	@GET
	@Produces(MediaType.APPLICATION_JSON)
	public Response checkForSearchMatches(@Context HttpServletRequest request) {
		
		
		/* Initial stuff */
		logger.info("Entering checkForSearchMatches");
		long methodStartTime = System.currentTimeMillis();
		HttpSession httpSession = request.getSession(true);
		Long userID = (Long)httpSession.getAttribute("serverSideUserID");
		if(userID == null) {
			String errorReason = "User not logged in";
			logger.severe(errorReason);
			return Response.status(401).build();
		}
		Objectify objectify = ObjectifyService.begin();
		
		
		/* Check for search results */
		// get token and results
		TwitterProfileChannel twitterProfileChannel = objectify.query(TwitterProfileChannel.class)
				.filter("twitterProfileID", userID).get();
		List<MatchedFollower> matchedFollowers = objectify.query(MatchedFollower.class).filter("token", twitterProfileChannel.getChannelToken()).list();
		
		
		/* End stuff */
		logger.info("Exiting checkForSearchMatches in " 
				+(System.currentTimeMillis() - methodStartTime)/1000d+ " secs");
		return Response.ok(gson.toJson(matchedFollowers)).build();
	}
	
	@Path("/remove")
	@DELETE
	@Produces(MediaType.TEXT_PLAIN)
	public Response deleteMatch(String text, @Context HttpServletRequest request) {
		
		
		/* Initial stuff */
		logger.info("Entering deleteMatch");
		long methodStartTime = System.currentTimeMillis();
		HttpSession httpSession = request.getSession(true);
		Long userID = (Long)httpSession.getAttribute("serverSideUserID");
		if(userID == null) {
			String errorReason = "User not logged in";
			logger.severe(errorReason);
			return Response.status(401).build();
		}
		if(text == null || text.isEmpty()) {
			String errorReason = "No text entered";
			logger.severe(errorReason);
			return Response.serverError().entity(errorReason).build();
		}
		Objectify objectify = ObjectifyService.begin();
		
		
		/* Delete Search phrase */
		// find twitter profile
		TwitterProfile twitterProfile = objectify.find(TwitterProfile.class, userID);
		if(twitterProfile == null) {
			String errorReason = "Twitter profile not found";
			logger.severe(errorReason);
			return Response.status(401).build();
		}
		
		// check to make sure search phrase hasn't already been added
		// if not persist
		String lowerCaseText = text.toLowerCase();
		SearchPhrase searchPhrase = objectify.query(SearchPhrase.class)
				.filter("twitterProfileID", twitterProfile.getId()).filter("text", lowerCaseText).get();
		if(searchPhrase != null) {
			objectify.delete(searchPhrase);
		}
		
		
		/* End stuff */
		logger.info("Exiting addMatch in " +(System.currentTimeMillis() - methodStartTime)/1000d+ " secs");
		return Response.ok().build();
	}
	
	@Path("/get")
	@GET
	@Produces(MediaType.APPLICATION_JSON)
	public Response getMatches(@Context HttpServletRequest request) {
		
		
		/* Initial stuff */
		logger.info("Entering getMatches");
		long methodStartTime = System.currentTimeMillis();
		HttpSession httpSession = request.getSession(true);
		Long userID = (Long)httpSession.getAttribute("serverSideUserID");
		if(userID == null) {
			String errorReason = "User not logged in";
			logger.severe(errorReason);
			return Response.status(401).build();
		}
		Objectify objectify = ObjectifyService.begin();
		
		
		/* Get Matches */
		// find twitter profile
		TwitterProfile twitterProfile = objectify.find(TwitterProfile.class, userID);
		if(twitterProfile == null) {
			String errorReason = "Twitter profile not found";
			logger.severe(errorReason);
			return Response.status(401).build();
		}
		
		// get matches
		List<SearchPhrase> searchPhrases = objectify.query(SearchPhrase.class)
				.filter("twitterProfileID", twitterProfile.getId()).list();
		List<String> matches = new ArrayList<String>();
		for(SearchPhrase searchPhrase : searchPhrases) {
			matches.add(searchPhrase.getText());
		}
		
		
		/* End stuff */
		logger.info("Exiting getMatches in " +(System.currentTimeMillis() - methodStartTime)/1000d+ " secs");
		return Response.ok(gson.toJson(matches)).build();
	}
}
